package com.ocom.srvpaccess.controller;


import com.google.gson.Gson;
import com.ocom.common.constant.SrvpAccessDeviceUrl;
import com.ocom.common.entity.access.EntityMjDeviceInfo;
import com.ocom.common.entity.master.EntityMjAppVerInfo;
import com.ocom.common.enums.MachEnum;
import com.ocom.common.resp.RespMachMessage;
import com.ocom.common.utils.RespUtilMach;
import com.ocom.common.utils.file.BinUtil;
import com.ocom.redis.util.RedisUtil;
import com.ocom.srvpaccess.service.MjAppVerInfoService;
import com.ocom.srvpaccess.service.MjDeviceInfoService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Slf4j
@RestController
public class BinDataController {

    @Autowired
    private MjDeviceInfoService deviceInfoService;

    @Autowired
    private MjAppVerInfoService appVerInfoService;


    @Resource
    private RedisUtil redisUtil;

    Logger logger= LoggerFactory.getLogger(BinDataController.class);

    // 获取二进制升级文件数据
    @GetMapping(value = SrvpAccessDeviceUrl.URLP_ACCESSDEVICE_getBinData)
    public RespMachMessage getBinData(Long companyId, String machNo, Integer lastBlockNum) throws IOException {
        //判断参数
        if (companyId <=0 || machNo==null|| lastBlockNum<0){
            return RespUtilMach.error(MachEnum.PARAMS_ERROR);
        }

        EntityMjDeviceInfo deviceInfo = deviceInfoService.getDeviceInfo(companyId, machNo);

        if (lastBlockNum.equals(0)){
            deviceInfoService.updateAppVerLast(companyId,machNo, deviceInfo.getAppVerTab());
        }
        //从门禁设备app版本信息表mj_app_ver_info查找apk_type=2、app_ver=mj_device_info . app_ver_tab的记录
        EntityMjAppVerInfo entityMjAppVerInfo = appVerInfoService.selectSinglechipAppVerInfo(deviceInfo.getAppVerTab());
        Map<String, Object> map = new HashMap<>();
        if (entityMjAppVerInfo !=null){
            //进redis
            String binDate= (String)redisUtil.get("MachBinData#url#"+entityMjAppVerInfo.getApkFileUrl());
            if(binDate==null){
//                byte[] fileToByte2 = BinUtil.getFileToByte(entityMjAppVerInfo.getApkFileUrl());
                URL url = new URL(entityMjAppVerInfo.getApkFileUrl());
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setConnectTimeout(5000);
                conn.setReadTimeout(60000);
                InputStream inputStream = conn.getInputStream();
                byte[] fileToByte2=read(inputStream);
                binDate=new Gson().toJson(fileToByte2);
                redisUtil.set("MachBinData#url#"+entityMjAppVerInfo.getApkFileUrl(),new Gson().toJson(fileToByte2),3600L);
            }
            byte[] fileToByte=new Gson().fromJson(binDate,byte[].class);

            int binBlockNum =(int) Math.ceil((double)fileToByte.length/512);

            logger.info("lastBlockNum:"+lastBlockNum);

            if (fileToByte.length > 0) {
                Integer blockDataSize = fileToByte.length;
                Integer splitSize = 512;
                int index = (lastBlockNum-1) * splitSize;
                index=index>0?index:0;
                List<Object> blockData = new ArrayList();
                int j = 0;
                while (j < splitSize && index < blockDataSize) {
                    blockData.add(byteToHex(fileToByte[index++]));
                    j++;
                }
                map.put("blockData", blockData);
                Integer blockSize = blockData.size();
                map.put("blockSize", blockSize);
                map.put("binBlockNum", binBlockNum);
                Long jobId = 512L * lastBlockNum + blockSize;
                //修改Jobid数据
                deviceInfoService.updateJobId(companyId, machNo, jobId);
                map.put("jobId", jobId);
                fileToByte.clone();

            }
        }

        return RespUtilMach.success(map);
    }

    // 更改升级文件数据状态（changeBinDataState）
    @PostMapping(value = SrvpAccessDeviceUrl.URLP_ACCESSDEVICE_changeBinDataState)
    public RespMachMessage changeBinDataState(Long companyId, String machNo, Long jobId){
        //判断参数
        if (companyId <=0 || machNo==null|| jobId<0){
            return RespUtilMach.error(MachEnum.PARAMS_ERROR);
        }
        Map<String, Object> map = new HashMap<>();
        EntityMjDeviceInfo deviceInfo = deviceInfoService.getDeviceInfo(companyId, machNo);
        if (deviceInfo!=null){
            //1、如果jobId != mj_device_info . app_ jobid则返回flag=0
            if (jobId!=deviceInfo.getAppJobid()){
                map.put("flag",0);
                return RespUtilMach.success(map);
            }
            //2、如果mj_device_info . app_ver_last != mj_device_info . app_ver_tab则返回flag=0
            if (deviceInfo.getAppVerLast()!=deviceInfo.getAppVerTab()){
                map.put("flag",0);
                return RespUtilMach.success(map);
            }
            //从门禁设备app版本信息表mj_app_ver_info查找apk_type=2、app_ver=mj_device_info . app_ver_tab的记录，
            EntityMjAppVerInfo entityMjAppVerInfo = appVerInfoService.selectSinglechipAppVerInfo(deviceInfo.getAppVerTab());
            //如果没有记录，返回flag=0
            if (entityMjAppVerInfo == null) {
                map.put("flag", 0);
                return RespUtilMach.success(map);
            }
            try {
                //有记录就打开mj_app_ver_info. apk_file_url文件，无法打开则返回flag=0
                byte[] fileToByte = BinUtil.getFileToByte(entityMjAppVerInfo.getApkFileUrl());
                if (fileToByte.length < jobId) {
                    map.put("flag", 0);
                    return RespUtilMach.success(map);
                }
                map.put("flag", 255);
                fileToByte.clone();
            } catch (Exception exception) {
                map.put("flag", 0);
                return RespUtilMach.success(map);

            }
        }
        return RespUtilMach.success(map);
    }

    /**
     * Byte字节转Hex
     * @param b 字节
     * @return Hex
     */
    public static String byteToHex(byte b){
        String hexString = Integer.toHexString(b & 0xFF);
        //由于十六进制是由0~9、A~F来表示1~16，所以如果Byte转换成Hex后如果是<16,就会是一个字符（比如A=10），通常是使用两个字符来表示16进制位的,
        //假如一个字符的话，遇到字符串11，这到底是1个字节，还是1和1两个字节，容易混淆，如果是补0，那么1和1补充后就是0101，11就表示纯粹的11
        if (hexString.length() < 2)
        {
            hexString = new StringBuilder(String.valueOf(0)).append(hexString).toString();
        }
        return hexString.toUpperCase();
    }

    private static byte[] read(InputStream inputStream) {
        ByteArrayOutputStream baos = null;
        try {
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int num = inputStream.read(buffer);
            while (num != -1) {
                baos.write(buffer, 0, num);
                num = inputStream.read(buffer);
            }
            baos.flush();
            return baos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (baos != null) {
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }


}
